package net.yunxinyong.sign.utils;

import com.google.common.collect.Lists;
import org.apache.poi.poifs.crypt.temp.SXSSFWorkbookWithCustomZipEntrySource;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.streaming.SXSSFCell;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;

import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

import java.util.Date;
import java.util.Iterator;
import java.util.List;

public class POIutils<T> {

    public void exportExcel(String sheetName, List<T> dataList, OutputStream outputStream) {
        SXSSFWorkbook workbook = new SXSSFWorkbookWithCustomZipEntrySource();
        try {
            SXSSFSheet sheet = workbook.createSheet(sheetName);
            sheet.setDefaultColumnWidth(40);

            CellStyle headerStyle = workbook.createCellStyle();
            headerStyle.setAlignment(HorizontalAlignment.CENTER);
            headerStyle.setBorderBottom(BorderStyle.THIN);
            headerStyle.setBorderTop(BorderStyle.THIN);
            headerStyle.setBorderRight(BorderStyle.THIN);
            headerStyle.setBorderLeft(BorderStyle.THIN);
            Font headerFont = workbook.createFont();
            headerFont.setColor((short) 12);
            headerFont.setFontHeightInPoints((short) 12);
            headerFont.setBold(true);
            headerStyle.setFont(headerFont);

            CellStyle contentStyle = workbook.createCellStyle();
            contentStyle.setBorderBottom(BorderStyle.THIN);
            contentStyle.setBorderLeft(BorderStyle.THIN);
            contentStyle.setBorderRight(BorderStyle.THIN);
            contentStyle.setBorderTop(BorderStyle.THIN);
            contentStyle.setAlignment(HorizontalAlignment.CENTER);
            contentStyle.setVerticalAlignment(VerticalAlignment.CENTER);
            Font contentFont = workbook.createFont();
            contentFont.setBold(false);
            contentFont.setFontHeightInPoints((short) 12);
            contentStyle.setFont(contentFont);

            if (ListUtils.isEmpty(dataList)) {
                return;
            }

            T tempT = dataList.get(0);
            Field[] headers = tempT.getClass().getDeclaredFields();
            List<String> headerList = Lists.newArrayListWithExpectedSize(headers.length);

            //获取字段注解的表头
            for (Field temp : headers) {
                if (0 == temp.getAnnotations().length) {
                    continue;
                }
                ExcelAnno exAnno = (ExcelAnno) temp.getAnnotations()[0];
                String header = exAnno.head();
                headerList.add(header);
            }
            //产生表格表头
            SXSSFRow row = sheet.createRow(0);
            row.setHeightInPoints(23);
            for (int i = 0; i < headerList.size(); i++) {
                SXSSFCell cell = row.createCell(i);
                cell.setCellStyle(headerStyle);
                RichTextString text = new XSSFRichTextString(headerList.get(i));
                cell.setCellValue(text);
            }
            //遍历集合，产生数据行
            Iterator<T> iterator = dataList.iterator();
            int index = 0;
            while (iterator.hasNext()) {
                index++;
                row = sheet.createRow(index);
                row.setHeightInPoints(20);
                T t = iterator.next();
                Field[] fields = t.getClass().getDeclaredFields();
                List<Field> fieldsList = Lists.newArrayListWithExpectedSize(fields.length);
                for (Field field : fields) {
                    if (field.getAnnotations().length != 0) {
                        fieldsList.add(field);
                    }
                }
                for (Field field : fieldsList) {
                    SXSSFCell cell = row.createCell(fieldsList.indexOf(field));
                    cell.setCellStyle(contentStyle);
                    String fieldName = field.getName();
                    String getMethodName = "get"
                            + fieldName.substring(0, 1).toUpperCase()
                            + fieldName.substring(1);
                    Class<?> tClass = t.getClass();
                    Method getMethod = tClass.getMethod(getMethodName);
                    Object value = getMethod.invoke(t);
                    try {
                        if (value instanceof Date) {
                            cell.setCellValue(DateUtils.format((Date) value, DateUtils.FORMAT_LONG));
                        } else {
                            cell.setCellValue(value.toString());
                        }
                    } catch (Exception ignored) {
                    }
                }
            }

            workbook.write(outputStream);
        } catch (Exception ignored) {
        } finally {
            try {
                workbook.close();
            } catch (IOException e) {
                workbook.dispose();
            }
        }
    }

}
